package com.zq.assistant.func;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * 选择数据控制器
 * Created by zhangqiang on 16-11-22.
 */

public class ChooseModeController<T> {

    private List<T> chooseDataList = new LinkedList<>();
    private Comparator<T> comparator;
    private LinkedList<OnEnableChangeListener> onEnableChangeListeners;
    private LinkedList<OnChooseDataChangeListener<T>> onChooseChangeListeners;
    private LinkedList<ChooseInterceptor<T>> chooseInterceptors;
    private boolean isEnable;
    private onAddEqualDataListener<T> onAddEqualDataListener;
    private int maxChoose = -1;
    private OnOverMaxChooseListener<T> onOverMaxChooseListener;

    public ChooseModeController() {

        onEnableChangeListeners = new LinkedList<>();
        onChooseChangeListeners = new LinkedList<>();
        chooseInterceptors = new LinkedList<>();
    }

    /**
     * 返回是否可用的状态
     *
     * @return
     */
    public boolean isEnable() {
        return isEnable;
    }

    /**
     * 设置是否可用
     *
     * @param enable
     */
    public void setEnable(boolean enable) {

        isEnable = enable;
        notifyEnableChange();
    }

    /**
     * 移除与指定数据列表相等的数据
     *
     * @param dataList 指定的数据列表
     * @return 移除的数量
     */
    public int removeChooseDataList(List<T> dataList) {

        if (dataList == null || dataList.isEmpty()) {
            return 0;
        }

        int deleteCount = 0;
        for (T data :
                chooseDataList) {

            deleteCount += removeChooseData(data, false);
        }
        if (deleteCount > 0) {
            notifyChooseChange();
        }
        return deleteCount;
    }

    /**
     * 是否为空
     * @return
     */
    public boolean isEmpty() {

        return this.chooseDataList == null || this.chooseDataList.isEmpty();
    }


    /**
     * 是否可用发生变化的监听
     */
    public interface OnEnableChangeListener {

        void onEnableChange(boolean isEnable);
    }

    /**
     * 选择的数据发生变化的监听
     *
     * @param <T>
     */
    public interface OnChooseDataChangeListener<T> {

        void onChooseDataChanged(List<T> dataList);
    }

    /**
     * 比较器
     *
     * @param <T>
     */
    public interface Comparator<T> {

        /**
         * 需要实现的比较方法
         *
         * @param chooseData 已选中的数据
         * @param addData    将要添加的数据
         * @return true表示相同，false表示不同
         */
        boolean compare(T chooseData, T addData);
    }

    /**
     * 清空并添加
     * @param data
     * @return
     */
    public boolean clearAndAddChooseData(T data){

        this.chooseDataList.clear();

        return addChooseData(data);
    }

    /**
     * 添加数据
     *
     * @param data
     * @return
     */
    public boolean addChooseData(T data) {

        if (data == null) {
            notifyChooseChange();
            return false;
        }

        if(isIntercepted(data)){
            return false;
        }

        T equalData = getEqualData(data);
        if (equalData != null) {

            if (onAddEqualDataListener == null || !onAddEqualDataListener.onAddEqualData(equalData, data)) {
                notifyChooseChange();
                return false;
            }
        }
        if (maxChoose >= 0 && getChooseCount() + 1 > maxChoose) {

            if (onOverMaxChooseListener != null) {
                onOverMaxChooseListener.onOverMaxWhenAddData(data, maxChoose);
            }
            notifyChooseChange();
            return false;
        }

        chooseDataList.add(data);
        notifyChooseChange();
        return true;
    }

    /**
     * 指定数据是否被选择
     *
     * @param data
     * @return
     */
    public boolean isChoose(T data) {

        return getEqualData(data) != null;
    }

    /**
     * 获取与制定数据相同的数据
     *
     * @param rawData
     * @return
     */
    public T getEqualData(T rawData) {

        for (T chooseData :
                chooseDataList) {

            if (isEqual(chooseData, rawData)) {
                return chooseData;
            }
        }
        return null;
    }

    /**
     * 获取选择的数量
     *
     * @return
     */
    public int getChooseCount() {

        return chooseDataList.size();
    }

    public List<T> getChooseDataList() {

        return new LinkedList<>(chooseDataList);
    }

    public ArrayList<T> getChooseDataArrayList() {

        return new ArrayList<>(chooseDataList);
    }


    /**
     * 设置比较器
     *
     * @param comparator
     */
    public void setComparator(Comparator<T> comparator) {
        this.comparator = comparator;
    }

    /**
     * 添加数据变更监听
     *
     * @param onChooseDataChangeListener
     */
    public void addOnChooseDataChangeListener(OnChooseDataChangeListener<T> onChooseDataChangeListener) {
        this.onChooseChangeListeners.add(onChooseDataChangeListener);
    }

    /**
     * 添加可用状态监听
     *
     * @param onEnableChangeListener
     */
    public void addOnEnableChangeListener(OnEnableChangeListener onEnableChangeListener) {
        this.onEnableChangeListeners.add(onEnableChangeListener);
    }

    /**
     * 改变可用状态
     */
    public void changeEnable() {

        setEnable(!isEnable());
    }

    /**
     * 通知模式开启
     */
    private void notifyEnableChange() {

        for (OnEnableChangeListener onEnableChangeListener :
                onEnableChangeListeners) {

            onEnableChangeListener.onEnableChange(isEnable());
        }
    }

    /**
     * 通知数据变更
     */
    public void notifyChooseChange() {

        for (OnChooseDataChangeListener<T> onChooseDataChangeListener :
                onChooseChangeListeners) {

            onChooseDataChangeListener.onChooseDataChanged(chooseDataList);
        }
    }

    public int removeChooseData(T data) {

        return removeChooseData(data, true);
    }

    /**
     * 移除最后一个选中的数据
     */
    public void removeChooseDataAtLast() {

        final int count = getChooseCount();

        if(count <= 0){
            return;
        }
        removeChooseDataAtIndex(count - 1);
    }

    public T getChooseDataAt(int position){

        return chooseDataList.get(position);
    }

    /**
     * 移除最后一个选中的数据
     */
    public void removeChooseDataAtIndex(int position) {
        if (position > chooseDataList.size() - 1 || position < 0) {
            return;
        }

        chooseDataList.remove(position);
        notifyChooseChange();

    }

    /**
     * 设置指定条目数据
     *
     * @param position
     */
    public boolean setChooseDataAtIndex(int position, T data) {
        if (position > chooseDataList.size() - 1 || position < 0) {
            return false;
        }

        if(isIntercepted(data)){
            return false;
        }

        chooseDataList.set(position,data);
        notifyChooseChange();
        return true;
    }

    /**
     * 删除与指定数据相同的数据
     *
     * @param data 指定数据
     * @return 删除的数量
     */
    public int removeChooseData(T data, boolean notify) {

        final int chooseCount = getChooseCount();
        if (chooseCount <= 0 || data == null) {
            return 0;
        }

        int deleteCount = 0;
        Iterator<T> iterator = chooseDataList.iterator();
        while (iterator.hasNext()) {

            T chooseData = iterator.next();
            if (isEqual(chooseData, data)) {

                iterator.remove();
                deleteCount++;
            }

        }
        if (deleteCount > 0 && notify) {
            notifyChooseChange();
        }
        return deleteCount;
    }

    /**
     * 根据删除规则删除数据
     *
     * @param deleteRule 删除规则
     * @return 删除的数量
     */
    public int removeChooseData(DeleteRule<T> deleteRule) {

        if (deleteRule == null) {
            return 0;
        }

        final int chooseCount = getChooseCount();
        if (chooseCount <= 0) {
            return 0;
        }

        int deleteCount = 0;
        Iterator<T> iterator = chooseDataList.iterator();
        while (iterator.hasNext()) {

            T data = iterator.next();
            if ( deleteRule.shouldDelete(data)) {

                iterator.remove();
                deleteCount++;
            }
        }

        if (deleteCount > 0) {
            notifyChooseChange();
        }
        return deleteCount;
    }


    /**
     * 是否相同 根据comparator
     *
     * @param data1
     * @param data2
     * @return
     */
    public boolean isEqual(T data1, T data2) {

        if (data1 == null || data2 == null) {
            return false;
        }

        if (comparator != null) {

            return comparator.compare(data1, data2);
        } else {

            return data1.equals(data2);
        }
    }

    /**
     * 制定的列表是否被全选
     *
     * @param dataList 制定的列表
     * @return
     */
    public boolean isAllChoose(List<T> dataList) {

        if (dataList == null || dataList.isEmpty()) {
            return false;
        }
        return getEqualCount(dataList) == dataList.size();
    }

    /**
     * 获取相同数据的数量
     *
     * @param dataList 制定的数据列表
     * @return 相同数据的数量
     */
    public int getEqualCount(List<T> dataList) {

        if (dataList == null || dataList.isEmpty()) {
            return 0;
        }

        int count = 0;

        for (T data :
                dataList) {

            if (getEqualData(data) != null) {

                count++;
            }
        }
        return count;
    }


    /**
     * 添加选择列表
     *
     * @param dataList
     * @return true添加成功，false添加失败
     */
    public boolean addChooseDataList(List<T> dataList) {

        if (dataList == null || dataList.isEmpty()) {

            notifyChooseChange();
            return false;
        }

        int count = 0;
        LinkedList<T> addDataList = new LinkedList<>();
        for (T data :
                dataList) {

            if(isIntercepted(data)){
                continue;
            }

            T equalData = getEqualData(data);

            if (equalData != null) {

                if (onAddEqualDataListener != null && onAddEqualDataListener.onAddEqualData(equalData, data)) {
                    count++;
                    addDataList.add(data);
                }
            } else {
                count++;
                addDataList.add(data);
            }
        }
        if (count <= 0) {
            notifyChooseChange();
            return false;
        }

        if (maxChoose >= 0 && getChooseCount() + count > maxChoose) {

            if (onOverMaxChooseListener != null) {

                onOverMaxChooseListener.onOverMaxWhenAddDataList(dataList, maxChoose);
            }
            notifyChooseChange();
            return false;
        }

        this.chooseDataList.addAll(addDataList);
        notifyChooseChange();
        return true;
    }

    public void clear() {

        this.chooseDataList.clear();
        notifyChooseChange();
    }


    public interface onAddEqualDataListener<T> {

        /**
         * 如果已经要添加的数据与已经添加的等值，这个方法会调用
         *
         * @param rawData 已经添加的数据
         * @param addData 将要添加的数据
         * @return 如果返回true，addData会添加到集合，如果false则不添加
         */
        boolean onAddEqualData(T rawData, T addData);
    }

    public void setOnAddEqualDataListener(ChooseModeController.onAddEqualDataListener<T> onAddEqualDataListener) {
        this.onAddEqualDataListener = onAddEqualDataListener;
    }

    /**
     * 监听添加数据超过最大值的接口
     *
     * @param <T>
     */
    public interface OnOverMaxChooseListener<T> {

        /**
         * 添加数据列表将要超过最大值时调用
         *
         * @param dataWillAdd 将要添加的数据
         * @param maxChoose   最大选择数量
         */
        void onOverMaxWhenAddData(T dataWillAdd, int maxChoose);

        /**
         * 添加数据列表将要超过最大值时调用
         *
         * @param dataListWillAdd 将要添加的数据列表
         * @param maxChoose       最大选择数量
         */
        void onOverMaxWhenAddDataList(List<T> dataListWillAdd, int maxChoose);
    }

    public int getMaxChoose() {
        return maxChoose;
    }

    /**
     * 设置最大的选择限制
     *
     * @param maxChoose
     */
    public void setMaxChoose(int maxChoose) {

        if (getChooseCount() > maxChoose) {
            throw new IllegalArgumentException("useless maxChoose :" + maxChoose + " because chooseCount " + getChooseCount() + " is larger");
        }

        this.maxChoose = maxChoose;
    }

    public void setOnOverMaxChooseListener(OnOverMaxChooseListener<T> onOverMaxChooseListener) {
        this.onOverMaxChooseListener = onOverMaxChooseListener;
    }

    /**
     * 删除的规则
     *
     * @param <T>
     */
    public interface DeleteRule<T> {

        boolean shouldDelete(T data);
    }


    public interface ChooseInterceptor<T>{

        boolean onInterceptChoose(T data);
    }

    public void addChooseInterceptor(ChooseInterceptor<T> chooseInterceptor){

        chooseInterceptors.add(chooseInterceptor);
    }

    public boolean isIntercepted(T data){

        for (ChooseInterceptor<T> interceptor:
             chooseInterceptors) {

            boolean isIntercepted = interceptor.onInterceptChoose(data);
            if(isIntercepted){
                return true;
            }
        }
        return false;
    }
}
